package com.whcoding.mongodb.util;

import com.mongodb.client.result.DeleteResult;
import com.mongodb.client.result.UpdateResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.geo.GeoResults;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.NearQuery;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Component;

import java.util.List;

/**
 * @Description: mongoDB 工具类，需要在业务模块配置MongoDB连接配置信息
 * <p>
 * spring.application.name=spirngboot-int-mongodbeg
 * spring.data.mongodb.database=admin
 * spring.data.mongodb.host=127.0.0.1
 * spring.data.mongodb.password=root
 * spring.data.mongodb.port=27017
 * spring.data.mongodb.username=root
 * @Auther:
 * @Date: 2020/8/14 11:09
 */

@Component
public class MongoDBUtil {

    @Autowired
    private MongoTemplate mongoTemplate;

    /**
     * 插入方法
     *
     * @param objectToSave
     */
    public void insert(Object objectToSave) {
        mongoTemplate.insert(objectToSave);
    }

    public void insert(Object objectToSave, String collectionName) {
        mongoTemplate.insert(objectToSave, collectionName);
    }

    public void insert(List<Object> objectToSave) {
        mongoTemplate.insert(objectToSave);
    }

    public void insert(List<Object> objectToSave, String collectionName) {
        mongoTemplate.insert(objectToSave, collectionName);
    }

    /**
     * 更新方法
     *
     * @param var1
     * @param var2
     * @param var3
     * @return
     */
    public UpdateResult update(Query var1, Update var2, Class<?> var3) {
        return mongoTemplate.updateFirst(var1, var2, var3);
    }

    public UpdateResult updateFirst(Query query, Update update, String collectionName) {
        return mongoTemplate.updateFirst(query, update, collectionName);
    }

    /**
     * 删除方法
     *
     * @param object
     * @return
     */
    public DeleteResult romove(Object object) {
        return mongoTemplate.remove(object);
    }

    public DeleteResult remove(Object object, String collectionName) {
        return mongoTemplate.remove(object, collectionName);
    }

    public DeleteResult remove(Query query, String collectionName) {
        return mongoTemplate.remove(query, collectionName);
    }

    public DeleteResult remove(Query query, Class<?> entityClass) {
        return mongoTemplate.remove(query, entityClass);
    }

    public DeleteResult remove(Query query, Class<?> entityClass, String collectionName) {

        return mongoTemplate.remove(query, entityClass, collectionName);
    }


    /**
     * 检查是否存在
     *
     * @param query
     * @param collectionName
     * @return
     */
    public boolean exists(Query query, String collectionName) {
        return mongoTemplate.exists(query, collectionName);
    }

    /**
     * 查询所有
     *
     * @param entityClass
     * @param <T>
     * @return
     */
    public <T> List<T> findAll(Class<T> entityClass) {
        return mongoTemplate.findAll(entityClass);
    }

    public <T> List<T> findAll(Class<T> entityClass, String collectionName) {
        return mongoTemplate.findAll(entityClass, collectionName);
    }

    public <T> List<T> find(Query query, Class<T> entityClass) {
        return mongoTemplate.find(query, entityClass);
    }

    public <T> List<T> find(Query query, Class<T> entityClass, String collectionName) {
        return mongoTemplate.find(query, entityClass, collectionName);
    }

    public <T> T findOne(Query query, Class<T> entityClass, String collectionName) {
        return mongoTemplate.findOne(query, entityClass, collectionName);
    }

    /**
     * MongDb分页公共方法
     *
     * @param clazz    实体类的class对象
     * @param pageSize 每页的数量
     * @param pageNum  当前的页数
     * @param query    query是啥不知道赶紧去查下，相当于sql语句
     * @return
     */
    public MongoPageResult paginationPageResult(Class clazz, int pageSize, int pageNum, Query query) {
        long total = this.mongoTemplate.count(query, clazz);
        Integer pages = (int) Math.ceil((double) total / (double) pageSize);
        if (pageNum <= 0 || pageNum > pages) {
            pageNum = 1;
        }
        int skip = pageSize * (pageNum - 1);
        query.skip(skip).limit(pageSize);
        List list = mongoTemplate.find(query, clazz);
        MongoPageResult pageResult = new MongoPageResult();
        pageResult.setTotal(total);
        pageResult.setPages(pages);
        pageResult.setPageSize(pageSize);
        pageResult.setPageNum(pageNum);
        pageResult.setList(list);
        return pageResult;
    }

    public <T> List<T> pagination(Class clazz, int pageSize, int pageNum, Query query) {
        int skip = pageSize * (pageNum - 1);
        query.skip(skip).limit(pageSize);
        List<T> list = mongoTemplate.find(query, clazz);
        return list;
    }

    /**
     * 查询符合条件的条数
     *
     * @param query
     * @param collectionName
     * @return
     */
    public long count(Query query, String collectionName) {
        return mongoTemplate.count(query, collectionName);
    }


    /**
     * MongDb分页公共方法
     *
     * @param clazz    实体类的class对象
     * @param pageSize 每页的数量
     * @param pageNum  当前的页数
     * @param query    query是啥不知道赶紧去查下，相当于sql语句
     * @return
     */
    public <T> List<T> query(Class<T> clazz, int pageSize, int pageNum, Query query) {

        int skip = pageSize * (pageNum - 1);
        query.skip(skip).limit(pageSize);
        List<T> list = mongoTemplate.find(query, clazz);
        return list;
    }

    /**
     * 空间搜索
     *
     * @param nearQuery
     * @param collectionName
     * @param <T>
     * @return
     */
    public <T> GeoResults<T> geoNear(NearQuery nearQuery, Class clazz, String collectionName) {
        return mongoTemplate.geoNear(nearQuery, clazz, collectionName);
    }


    public <T> GeoResults<T> geoNear(NearQuery nearQuery, Query query, String collectionName, int pageSize, int pageNum, Class clazz) {
        int skip = pageSize * (pageNum - 1);
        query.skip(skip).limit(pageSize);
        nearQuery.query(query);
        return mongoTemplate.geoNear(nearQuery, clazz, collectionName);
    }

}
